﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using System.Web.Configuration;
using FlashCards.WebApp.DataAccessLayer;
using FlashCards.Model;
using System.Web.Security;
using System.Text;

namespace FlashCards.WebApp.Security
{
    public class FlashcardsMembershipProvider : System.Web.Security.MembershipProvider
    {
        public override string ApplicationName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(oldPassword) && !string.IsNullOrEmpty(newPassword))
            {
                using (var context = new FlashCardsEntities())
                {
                    var membership = context.Memberships.FirstOrDefault(x => x.User.Nick == username);
                    if (membership.Password != GetSaltedPasswordHash(username, oldPassword))
                        return false;

                    membership.Password = GetSaltedPasswordHash(username, newPassword);
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            throw new NotImplementedException();
        }

        public override System.Web.Security.MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out System.Web.Security.MembershipCreateStatus status)
        {
            //sprawdzenie unikalności username
            using (var context = new FlashCardsEntities())
            {
                if (context.Users.FirstOrDefault(x => x.Nick == username) != null)
                {
                    status = MembershipCreateStatus.DuplicateUserName;
                    return null;
                }
            }

            //sprawdzenie unikalności email
            using (var context = new FlashCardsEntities())
            {
                if (context.Memberships.FirstOrDefault(x => x.Email == email) != null)
                {
                    status = MembershipCreateStatus.DuplicateEmail;
                    return null;
                }
            }

            User usr = new User();
            usr.Nick = username;

            FlashCards.Model.Membership mem = new FlashCards.Model.Membership();
            mem.Password = Convert.ToBase64String(System.Security.Cryptography.MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(password)));
            mem.Email = email;

            UserUtils.CreateUser(usr, mem);

            status = System.Web.Security.MembershipCreateStatus.Success;

            return GetUser(username, true);
        }

        public static void CreateUserAdditionalData(string nick, string name, string surname, DateTime? birthDate)
        {
            using (var context = new FlashCardsEntities())
            {
                var user = context.Users.FirstOrDefault(x => x.Nick == nick);
                if (user != null)
                {
                    user.Name = name;
                    user.Surname = surname;
                    user.BirthDate = birthDate;

                    context.SaveChanges();
                }
            }
        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            throw new NotImplementedException();
        }

        public override bool EnablePasswordReset
        {
            get { throw new NotImplementedException(); }
        }

        public override bool EnablePasswordRetrieval
        {
            get { throw new NotImplementedException(); }
        }

        public override System.Web.Security.MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override System.Web.Security.MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override System.Web.Security.MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException();
        }

        public override string GetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override System.Web.Security.MembershipUser GetUser(string username, bool userIsOnline)
        {
            User user = null;
            using (var context = new FlashCardsEntities())
            {
                user = context.Users.FirstOrDefault(x => x.Nick == username);
            }
            if (user != null)
            {
                MembershipUser memUser = new MembershipUser("AspNetSqlMembershipProvider", username, user.UserId, string.Empty, string.Empty, string.Empty, true, false, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue);
                return memUser;
            }
            return null;
        }

        public override System.Web.Security.MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override string GetUserNameByEmail(string email)
        {
            throw new NotImplementedException();
        }

        public override int MaxInvalidPasswordAttempts
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredPasswordLength
        {
            get
            {
                int defaultValue = 3;
                MembershipSection membershipSection = ConfigurationManager.GetSection("system.web/membership") as MembershipSection;
                if (membershipSection != null)
                {
                    ProviderSettings settings = membershipSection.Providers["AspNetSqlMembershipProvider"];
                    if (settings != null)
                    {
                        try
                        {
                            return int.Parse(settings.Parameters["minRequiredPasswordLength"]);
                        }
                        catch (Exception ex)
                        {
                            return defaultValue;
                        }
                    }
                    else
                        return defaultValue;
                }
                else
                    return defaultValue;
            }
        }

        public override int PasswordAttemptWindow
        {
            get { throw new NotImplementedException(); }
        }

        public override System.Web.Security.MembershipPasswordFormat PasswordFormat
        {
            get { throw new NotImplementedException(); }
        }

        public override string PasswordStrengthRegularExpression
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresQuestionAndAnswer
        {
            get { return false; }
        }

        public override bool RequiresUniqueEmail
        {
            get { return true; }
        }

        public override string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override bool UnlockUser(string userName)
        {
            throw new NotImplementedException();
        }

        public override void UpdateUser(System.Web.Security.MembershipUser user)
        {
            throw new NotImplementedException();
        }

        public override bool ValidateUser(string username, string password)
        {
            using (var context = new FlashCardsEntities())
            {
                var user = context.Users.FirstOrDefault(x => x.Nick == username);
                if (user != null)
                {
                    var membership = context.Memberships.FirstOrDefault(x => x.UserId == user.UserId);

                    membership.LastLoginDate = DateTime.Now;

                    if (membership.Password == password || membership.Password == GetPasswordHash(password))
                    {
                        membership.Password = GetSaltedPasswordHash(username, password);
                    }

                    context.SaveChanges();

                    if (membership.Password == GetSaltedPasswordHash(username, password))
                        return true;
                    return false;
                }
                else
                {
                    return false;
                }
            }
        }

        static string GetSaltedPasswordHash(string username, string password)
        {
            return GetPasswordHash(string.Format("{0}{1}", username, password));
        }

        static string GetPasswordHash(string password)
        {
            return Convert.ToBase64String(System.Security.Cryptography.MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(password)));
        }
    }
}